package com.autowite.autowite.utils;

import com.alibaba.excel.util.StringUtils;
import com.google.common.io.Files;
import org.openqa.selenium.*;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.Select;
import org.openqa.selenium.support.ui.WebDriverWait;

import java.io.File;
import java.io.IOException;
import java.time.Duration;

public class SeleniumUtils {

    private final WebDriver driver;

    /**
     * 构造函数，传入 WebDriver 实例。
     *
     * @param driver WebDriver 实例
     */
    public SeleniumUtils(WebDriver driver) {
        this.driver = driver;
    }

    /**
     * 打开指定的网页。
     *
     * @param url 网页地址
     *            使用方法：
     *    <pre>
     *   utils.openPage("https://example.com");
     *   </pre>
     */
    public void openPage(String url) {
        driver.get(url);
    }

    /**
     * 填充输入框。
     *
     * @param fieldId 输入框的 ID
     * @param value   要输入的值
     *                使用方法：
     *                <pre>
     *                               utils.fillInputField("username", "testuser");
     *                               </pre>
     */
    public void fillInputField(String fieldId, String value) {
        WebElement field = driver.findElement(By.id(fieldId));
        field.clear(); // 清空输入框
        field.sendKeys(value);
    }

    /**
     * 选择下拉框的值。
     *
     * @param dropdownId 下拉框的 ID
     * @param value      要选择的值
     *                   使用方法：
     *                   <pre>
     *                                     utils.selectDropdown("country", "China");
     *                                     </pre>
     */
    public void selectDropdown(String dropdownId, String value) {
        WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
        WebElement dropdown = driver.findElement(By.id(dropdownId));
        wait.until(ExpectedConditions.visibilityOf(dropdown));
        new Select(dropdown).selectByValue(value);
    }

    /**
     * 点击按钮。
     *
     * @param buttonId 按钮的 ID
     *                 使用方法：
     *         <pre>
     *          utils.clickButton("submitBtn");
     *         </pre>
     */
    public void clickButton(String buttonId) {
        WebElement button = driver.findElement(By.id(buttonId));
        button.click();
    }

    /**
     * 提交表单。
     *
     * @param submitId 提交按钮的 ID，默认值为 "submit"
     *                 使用方法：
     *                 <pre>
     *                                 utils.submitForm("submitBtn");
     *                                 </pre>
     */
    public void submitForm(String submitId) {
        String finalSubmitId = StringUtils.isEmpty(submitId) ? "submit" : submitId;
        WebElement submitButton = driver.findElement(By.id(finalSubmitId));
        submitButton.click();
    }

    /**
     * 关闭浏览器。
     * 使用方法：
     * <pre>
     * utils.close();
     * </pre>
     */
    public void close() {
        driver.quit();
    }

    /**
     * 等待元素可见。
     *
     * @param by      定位器
     * @param timeout 等待时间（秒）
     *                使用方法：
     *                <pre>
     *                               utils.waitForElementVisible(By.id("username"), 10);
     *                               </pre>
     */
    public void waitForElementVisible(By by, int timeout) {
        WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(timeout));
        wait.until(ExpectedConditions.visibilityOfElementLocated(by));
    }

    /**
     * 等待元素可点击。
     *
     * @param by      定位器
     * @param timeout 等待时间（秒）
     *                使用方法：
     *                <pre>
     *                               utils.waitForElementClickable(By.id("submitBtn"), 10);
     *                               </pre>
     */
    public void waitForElementClickable(By by, int timeout) {
        WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(timeout));
        wait.until(ExpectedConditions.elementToBeClickable(by));
    }

    /**
     * 等待元素存在。
     *
     * @param by      定位器
     * @param timeout 等待时间（秒）
     *                使用方法：
     *                <pre>
     *                               utils.waitForElementPresent(By.id("username"), 10);
     *                               </pre>
     */
    public void waitForElementPresent(By by, int timeout) {
        WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(timeout));
        wait.until(ExpectedConditions.presenceOfElementLocated(by));
    }

    /**
     * 获取元素文本。
     *
     * @param by 定位器
     * @return 元素文本
     * 使用方法：
     * <pre>
     * String text = utils.getElementText(By.id("welcomeMessage"));
     * System.out.println(text);
     * </pre>
     */
    public String getElementText(By by) {
        return driver.findElement(by).getText();
    }

    /**
     * 获取元素属性值。
     *
     * @param by            定位器
     * @param attributeName 属性名称
     * @return 属性值
     * 使用方法：
     * <pre>
     * String value = utils.getElementAttribute(By.id("username"), "placeholder");
     * System.out.println(value);
     * </pre>
     */
    public String getElementAttribute(By by, String attributeName) {
        return driver.findElement(by).getAttribute(attributeName);
    }

    /**
     * 获取元素的 HTML 内容。
     *
     * @param by 定位器
     * @return 元素的 HTML 内容
     * 使用方法：
     * <pre>
     * String html = utils.getElementHtml(By.id("container"));
     * System.out.println(html);
     * </pre>
     */
    public String getElementHtml(By by) {
        return driver.findElement(by).getAttribute("outerHTML");
    }

    /**
     * 切换到弹窗。
     * 使用方法：
     * <pre>
     * utils.switchToAlert();
     * </pre>
     */
    public void switchToAlert() {
        driver.switchTo().alert();
    }

    /**
     * 接受弹窗。
     * 使用方法：
     * <pre>
     * utils.acceptAlert();
     * </pre>
     */
    public void acceptAlert() {
        driver.switchTo().alert().accept();
    }

    /**
     * 拒绝弹窗。
     * 使用方法：
     * <pre>
     * utils.dismissAlert();
     * </pre>
     */
    public void dismissAlert() {
        driver.switchTo().alert().dismiss();
    }

    /**
     * 切换到指定的 iframe。
     *
     * @param iframeId iframe 的 ID 或定位器
     *                 使用方法：
     *                 <pre>
     *                                 utils.switchToIframe("iframe1");
     *                                 </pre>
     */
    public void switchToIframe(String iframeId) {
        driver.switchTo().frame(iframeId);
    }

    /**
     * 切换回主文档。
     * 使用方法：
     * <pre>
     * utils.switchToDefaultContent();
     * </pre>
     */
    public void switchToDefaultContent() {
        driver.switchTo().defaultContent();
    }

    /**
     * 滚动到页面底部。
     * 使用方法：
     * <pre>
     * utils.scrollToBottom();
     * </pre>
     */
    public void scrollToBottom() {
        ((JavascriptExecutor) driver).executeScript("window.scrollTo(0, document.body.scrollHeight);");
    }

    /**
     * 滚动到指定元素。
     *
     * @param by 定位器
     *           使用方法：
     *           <pre>
     *                     utils.scrollToElement(By.id("footer"));
     *                     </pre>
     */
    public void scrollToElement(By by) {
        WebElement element = driver.findElement(by);
        ((JavascriptExecutor) driver).executeScript("arguments[0].scrollIntoView(true);", element);
    }

    /**
     * 判断元素是否存在。
     *
     * @param by 定位器
     * @return 是否存在
     * 使用方法：
     * <pre>
     * boolean exists = utils.isElementPresent(By.id("username"));
     * System.out.println("Element exists: " + exists);
     * </pre>
     */
    public boolean isElementPresent(By by) {
        try {
            driver.findElement(by);
            return true;
        } catch (NoSuchElementException e) {
            return false;
        }
    }

    /**
     * 判断元素是否可见。
     *
     * @param by 定位器
     * @return 是否可见
     * 使用方法：
     * <pre>
     * boolean visible = utils.isElementVisible(By.id("username"));
     * System.out.println("Element is visible: " + visible);
     * </pre>
     */
    public boolean isElementVisible(By by) {
        try {
            return driver.findElement(by).isDisplayed();
        } catch (NoSuchElementException e) {
            return false;
        }
    }

    /**
     * 判断元素是否可点击。
     *
     * @param by 定位器
     * @return 是否可点击
     * 使用方法：
     * <pre>
     * boolean clickable = utils.isElementClickable(By.id("submitBtn"));
     * System.out.println("Element is clickable: " + clickable);
     * </pre>
     */
    public boolean isElementClickable(By by) {
        try {
            new WebDriverWait(driver, Duration.ofSeconds(5))
                    .until(ExpectedConditions.elementToBeClickable(by));
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 执行 JavaScript 脚本。
     *
     * @param script 脚本内容
     *               使用方法：
     *               <pre>
     *               utils.executeScript("window.scrollTo(0, 500);");
     *               </pre>
     */
    public void executeScript(String script) {
        ((JavascriptExecutor) driver).executeScript(script);
    }

    /**
     * 获取 WebDriver 实例。
     *
     * @return WebDriver 实例
     * 使用方法：
     * <pre>
     * WebDriver driver = utils.getDriver();
     * </pre>
     */
    public WebDriver getDriver() {
        return driver;
    }

    /**
     * 刷新当前页面。
     * 使用方法：
     * <pre>
     * utils.refreshPage();
     * </pre>
     */
    public void refreshPage() {
        driver.navigate().refresh();
    }

    /**
     * 后退到上一个页面。
     * 使用方法：
     * <pre>
     * utils.goBack();
     * </pre>
     */
    public void goBack() {
        driver.navigate().back();
    }

    /**
     * 前进到下一个页面。
     * 使用方法：
     * <pre>
     * utils.goForward();
     * </pre>
     */
    public void goForward() {
        driver.navigate().forward();
    }

    /**
     * 获取当前页面的 URL。
     *
     * @return 当前页面的 URL
     * 使用方法：
     * <pre>
     * String url = utils.getCurrentUrl();
     * System.out.println(url);
     * </pre>
     */
    public String getCurrentUrl() {
        return driver.getCurrentUrl();
    }

    /**
     * 获取当前页面的标题。
     *
     * @return 当前页面的标题
     * 使用方法：
     * <pre>
     * String title = utils.getPageTitle();
     * System.out.println(title);
     * </pre>
     */
    public String getPageTitle() {
        return driver.getTitle();
    }

    /**
     * 截图并保存到指定路径。
     *
     * @param filePath 截图保存路径
     *                 使用方法：
     *                 <pre>
     *                 utils.takeScreenshot("C:\\screenshots\\screenshot.png");
     *                 </pre>
     */
    public void takeScreenshot(String filePath) {
        if (driver instanceof TakesScreenshot) {
            File screenshot = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
            try {
                Files.copy(screenshot, new File(filePath));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 清除浏览器缓存。
     * 使用方法：
     * <pre>
     * utils.clearBrowserCache();
     * </pre>
     */
    public void clearBrowserCache() {
        driver.manage().deleteAllCookies();
    }

}
